package fastwave.common.auth.config;

import fastwave.common.auth.constant.SecurityConstants;
import fastwave.common.auth.service.MyClientDetailsService;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.token.TokenStore;

import javax.sql.DataSource;

@Configuration
@EnableAuthorizationServer
@RequiredArgsConstructor
public class OAuth2ServerConfig extends AuthorizationServerConfigurerAdapter {
    final AuthenticationManager authenticationManager;
    final PasswordEncoder passwordEncoder;
    final DataSource dataSource;
    final TokenStore tokenStore;

    /**
     * 在内存中存储测试客户端与凭证(实际应用用数据库)
     * 用来配置客户端详情服务,客户端详情信息在这里进行初始化，
     * 你能够把客户端详情信息写死在这里或者是通过数据库来存储调取详情信息
     * @param clients
     * @throws Exception
     */
    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        /* 仅用于测试，不需要连接数据库
        clients.inMemory()
                .withClient("app")
                .secret(passwordEncoder.encode("123"))
                .authorizedGrantTypes("password","refresh_token")
                .scopes("app")
                .resourceIds("goods");
         */

        // System.out.println(passwordEncoder.encode("123"));
        // 123 $2a$10$04XiVwNxl2NuYdd37cqkwOK91mKiWWU4A2PK12I0dDdxWTlNq0kDS
        // base64 app:123 Basic YXBwOjEyMw==  Authorization

        MyClientDetailsService clientDetailsService = new MyClientDetailsService(dataSource);
        clientDetailsService.setSelectClientDetailsSql(SecurityConstants.DEFAULT_SELECT_STATEMENT);
        clientDetailsService.setFindClientDetailsSql(SecurityConstants.DEFAULT_FIND_STATEMENT);
        clients.withClientDetails(clientDetailsService);
    }

    /**
     * 设置token
     * @param endpoints
     * @throws Exception
     */
    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        // authenticationManager 配合 password 模式使用
        endpoints.authenticationManager(authenticationManager);

        // 允许请求 token 的请求方式
        endpoints.allowedTokenEndpointRequestMethods(HttpMethod.GET,HttpMethod.POST);
        endpoints.tokenStore(tokenStore);
    }

    /**
     * /oauth/authorize(授权端，授权码模式使用)
     * /oauth/token(令牌端，获取 token)
     * /oauth/check_token(资源服务器用来校验token)
     * /oauth/confirm_access(用户发送确认授权)
     * /oauth/error(认证失败)
     * /oauth/token_key(如果使用JWT，可以获的公钥用于 token 的验签)
     * @param security
     * @throws Exception
     */
    @Override
    public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
        // 允许表单认证
        security.allowFormAuthenticationForClients();
    }
}
